home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 41 / Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso / -seriously_amiga- / programming / other / gtlayout / source / ltp_tabclass.c < prev    next >
C/C++ Source or Header  |  1999-04-19  |  16KB  |  766 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1998 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. /*****************************************************************************/
  15.  
  16. #include <intuition/classes.h>
  17.  
  18. #include <exec/memory.h>
  19. #include <hardware/blit.h>
  20.  
  21. #include <clib/alib_protos.h>    /* For Coerce/Do/DoSuperMethod */
  22.  
  23. #include <stdarg.h>
  24.  
  25. /*****************************************************************************/
  26.  
  27. #include "Assert.h"
  28.  
  29. #ifdef DO_TAB_KIND    /* Support code */
  30.  
  31. #define TIA_Labels        (TAG_USER+0x90000)
  32. #define TIA_Font        (TAG_USER+0x90001)
  33. #define TIA_Screen        (TAG_USER+0x90002)
  34. #define TIA_Index        (TAG_USER+0x90003)
  35. #define TIA_DrawInfo    (TAG_USER+0x90004)
  36. #define TIA_SizeType    (TAG_USER+0x90005)
  37.  
  38. STATIC VOID
  39. DrawCap(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height,BOOL Flip)
  40. {
  41.     LONG x,y,da,MidX,MidY,r,Full,Push,Mult;
  42.  
  43.     Full = Height;
  44.  
  45.     Height = Width;
  46.  
  47.     MidX = Left;
  48.     MidY = Top + Height - 1;
  49.  
  50.     r = Height - 1;
  51.  
  52.     x = 0;
  53.     y = r;
  54.     da = r - 1;
  55.  
  56.     if(Flip)
  57.     {
  58.         Push = Width - 1;
  59.         Mult = -1;
  60.     }
  61.     else
  62.     {
  63.         Push = 0;
  64.         Mult = 1;
  65.     }
  66.  
  67.     do
  68.     {
  69.         if(da < 0)
  70.         {
  71.             y--;
  72.  
  73.             da += y * 2;
  74.         }
  75.  
  76.         WritePixel(RPort,Left + Push + Mult * (x + MidX - Left),-y + MidY);
  77.         WritePixel(RPort,Left + Push + Mult * (y + MidX - Left),-x + MidY);
  78.  
  79.         da -= (1 + x * 2);
  80.  
  81.         x++;
  82.     }
  83.     while(x <= y);
  84.  
  85.     Left += Width - 1 - Push;
  86.  
  87.     LTP_DrawLine(RPort,Left,Top + Height,Left,Top + Full - 1);
  88. }
  89.  
  90. STATIC VOID
  91. RenderTabs(struct RastPort *RPort,struct Gadget *gadget,TabInfo *Info,UWORD *Pens,LONG Pull)
  92. {
  93.     LONG    Width,Height;
  94.     LONG    i;
  95.     LONG    Pen;
  96.  
  97.     Width    = Info->TabWidth;
  98.     Height    = Info->TabHeight;
  99.  
  100.     SetRast(&Info->RPort,Pens[BACKGROUNDPEN]);
  101.  
  102.     for(i = 0 ; i < 4 ; i++)
  103.     {
  104.         if(i & 1)
  105.         {
  106.             if(Pens[SHINEPEN] == Pens[SHADOWPEN])
  107.                 Pen = BACKGROUNDPEN;
  108.             else
  109.                 Pen = SHADOWPEN;
  110.         }
  111.         else
  112.             Pen = SHINEPEN;
  113.  
  114.         LTP_SetAPen(&Info->RPort,Pens[Pen]);
  115.  
  116.         LTP_DrawLine(&Info->RPort,0,Height - 1 - i,gadget->Width - 1 - Info->Thick * i,Height - 1 - i);
  117.     }
  118.  
  119.     for(i = Info->Count - 1 ; i >= 0 ; i--)
  120.     {
  121.         if(i != Info->Current)
  122.             BltMaskBitMapRastPort(Info->Tabs[i].BitMap,0,0,&Info->RPort,Info->Tabs[i].Left,4,Width,Height - 6,ABC|ABNC|ANBC,Info->Mask);
  123.     }
  124.  
  125.     BltMaskBitMapRastPort(Info->Tabs[Info->Current].BitMap,0,0,&Info->RPort,Info->Tabs[Info->Current].Left,0,Width,Height - Pull,ABC|ABNC|ANBC,Info->Mask);
  126.  
  127.     WaitBlit();
  128.  
  129.     BltBitMapRastPort(Info->BitMap,0,0,RPort,gadget->LeftEdge,gadget->TopEdge + gadget->Height - (Info->TabHeight + 2),gadget->Width,Info->TabHeight,0xC0);
  130. }
  131.  
  132. STATIC VOID
  133. SetMethod(struct IClass *class,struct Gadget *gadget,struct opSet *SetInfo)
  134. {
  135.     TabInfo            *Info = INST_DATA(class,gadget);
  136.     struct TagItem    *Tag;
  137.     BOOL             NeedRefresh = FALSE;
  138.     BOOL             Disabled;
  139.  
  140.     Disabled = (BOOL)((gadget->Flags & GFLG_DISABLED) != 0);
  141.  
  142.     if(Tag = FindTagItem(GA_Disabled,SetInfo->ops_AttrList))
  143.     {
  144.         if(Tag->ti_Data && !Disabled || !Tag->ti_Data && Disabled)
  145.             NeedRefresh = TRUE;
  146.     }
  147.  
  148.     if(Tag = FindTagItem(TIA_Index,SetInfo->ops_AttrList))
  149.     {
  150.         LONG Index = Tag->ti_Data;
  151.  
  152.         if(Index >= Info->Count)
  153.             Index = Info->Count - 1;
  154.  
  155.         if(Index != Info->Current)
  156.         {
  157.             Info->Initial = Info->Current = Index;
  158.  
  159.             NeedRefresh = TRUE;
  160.         }
  161.     }
  162.  
  163.     if(NeedRefresh)
  164.     {
  165.         struct RastPort *RPort;
  166.  
  167.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  168.         {
  169.             DoMethod((Object *)gadget,GM_RENDER,SetInfo->ops_GInfo,RPort,GREDRAW_REDRAW);
  170.  
  171.             ReleaseGIRPort(RPort);
  172.         }
  173.     }
  174. }
  175.  
  176. STATIC ULONG
  177. RenderMethod(struct IClass *class,struct Gadget *gadget,struct gpRender *RenderInfo)
  178. {
  179.     TabInfo *Info = INST_DATA(class,gadget);
  180.  
  181.     RenderTabs(RenderInfo->gpr_RPort,gadget,Info,RenderInfo->gpr_GInfo->gi_DrInfo->dri_Pens,RenderInfo->gpr_Redraw == GREDRAW_UPDATE ? 2 : 0);
  182.  
  183.     return(TRUE);
  184. }
  185.  
  186. STATIC VOID
  187. DisposeMethod(struct IClass *class,struct Gadget *gadget,Msg msg)
  188. {
  189.     TabInfo *Info = INST_DATA(class,gadget);
  190.  
  191.     if(Info->Mask || Info->Tabs || Info->BitMap)
  192.         WaitBlit();
  193.  
  194.     if(Info->Mask)
  195.     {
  196.         FreeRaster(Info->Mask,Info->TabWidth,Info->TabHeight);
  197.     }
  198.  
  199.     if(Info->Tabs)
  200.     {
  201.         LONG i;
  202.  
  203.         for(i = 0 ; i < Info->Count ; i++)
  204.             LTP_DeleteBitMap(Info->Tabs[i].BitMap,TRUE);
  205.  
  206.         FreeVec(Info->Tabs);
  207.     }
  208.  
  209.     LTP_DeleteBitMap(Info->BitMap,FALSE);
  210. }
  211.  
  212. STATIC ULONG
  213. NewMethod(struct IClass *class,struct Gadget *gadget,struct opSet *SetInfo)
  214. {
  215.     if(gadget = (struct Gadget *)DoSuperMethodA(class,(Object *)gadget,(Msg)SetInfo))
  216.     {
  217.         TabInfo            *Info = INST_DATA(class,gadget);
  218.         struct TagItem    *Tag,*TagList = SetInfo->ops_AttrList;
  219.         struct TextAttr    *FontAttr;
  220.         LONG             Width,Height;
  221.         struct DrawInfo    *DrawInfo;
  222.         STRPTR            *Labels;
  223.         struct Screen    *Screen;
  224.  
  225.         Width        = 0;
  226.         Height        = 0;
  227.  
  228.         FontAttr    = NULL;
  229.         DrawInfo    = NULL;
  230.         Labels        = NULL;
  231.         Screen        = NULL;
  232.  
  233.         memset(Info,0,sizeof(TabInfo));
  234.  
  235.         while(Tag = NextTagItem(&TagList))
  236.         {
  237.             switch(Tag->ti_Tag)
  238.             {
  239.                 case GA_Width:
  240.                     Width = Tag->ti_Data;
  241.                     break;
  242.  
  243.                 case GA_Height:
  244.                     Height = Tag->ti_Data;
  245.                     break;
  246.  
  247.                 case TIA_Labels:
  248.                     Labels = (STRPTR *)Tag->ti_Data;
  249.                     break;
  250.  
  251.                 case TIA_Font:
  252.                     FontAttr = (struct TextAttr *)Tag->ti_Data;
  253.                     break;
  254.  
  255.                 case TIA_Screen:
  256.                     Screen = (struct Screen *)Tag->ti_Data;
  257.                     break;
  258.  
  259.                 case TIA_Index:
  260.                     Info->Current = Tag->ti_Data;
  261.                     break;
  262.  
  263.                 case TIA_DrawInfo:
  264.                     DrawInfo = (struct DrawInfo *)Tag->ti_Data;
  265.                     break;
  266.             }
  267.         }
  268.  
  269.         if(Labels)
  270.         {
  271.             while(Labels[Info->Count])
  272.                 Info->Count++;
  273.         }
  274.  
  275.         if(Screen && DrawInfo && FontAttr && Width && Height && Labels && Info->Count)
  276.         {
  277.             struct TextFont *Font;
  278.  
  279.             if(Font = OpenFont(FontAttr))
  280.             {
  281.                 struct RastPort *RPort = &Info->RPort;
  282.  
  283.                 InitRastPort(RPort);
  284.  
  285.                 SetFont(RPort,Font);
  286.  
  287.                 if(Height >= RPort->TxHeight + 11)
  288.                 {
  289.                     LONG i,Len,MaxWidth,Remain;
  290.                     LONG Lean;
  291.  
  292.                     if(Info->Current < 0)
  293.                         Info->Current = 0;
  294.                     else
  295.                     {
  296.                         if(Info->Current >= Info->Count)
  297.                             Info->Current = Info->Count - 1;
  298.                     }
  299.  
  300.                     Lean = (TextLength(RPort,"O",1) + 1) / 2;
  301.  
  302.                     Info->Thick    = (DrawInfo->dri_Resolution.Y + DrawInfo->dri_Resolution.X - 1) / DrawInfo->dri_Resolution.X;
  303.  
  304.                     if(Info->Thick < 1)
  305.                         Info->Thick = 1;
  306.  
  307.                     for(i = MaxWidth = 0 ; i < Info->Count ; i++)
  308.                     {
  309.                         if((Len = TextLength(RPort,Labels[i],strlen(Labels[i]))) > MaxWidth)
  310.                             MaxWidth = Len;
  311.                     }
  312.  
  313.                     MaxWidth = Info->Thick + (Lean + Info->Thick - 1 + Info->Thick + MaxWidth + Info->Thick + Lean + Info->Thick - 1) + Info->Thick;
  314.  
  315.                     Remain = (Width - MaxWidth - 5 * Info->Thick) / (Info->Thick * 4);
  316.  
  317.                     if(Remain >= Info->Count - 1)
  318.                     {
  319.                         if(Info->Tabs = (TabEntry *)AllocVec(sizeof(TabEntry) * Info->Count,MEMF_ANY|MEMF_CLEAR))
  320.                         {
  321.                             STATIC const BYTE PenNumbers[] =
  322.                             {
  323.                                 BACKGROUNDPEN,
  324.                                 SHINEPEN,
  325.                                 SHADOWPEN,
  326.                                 TEXTPEN
  327.                             };
  328.  
  329.                             struct BitMap     Mask;
  330.                             LONG             Depth;
  331.                             LONG             MaxPen;
  332.                             UWORD            *Pens = DrawInfo->dri_Pens;
  333.                             BOOL             GotIt = TRUE;
  334.  
  335.                             memset(&Mask,0,sizeof(Mask));
  336.  
  337.                             for(i = 0, MaxPen = -1 ; i < sizeof(PenNumbers) ; i++)
  338.                             {
  339.                                 if(Pens[PenNumbers[i]] > MaxPen)
  340.                                     MaxPen = Pens[PenNumbers[i]];
  341.                             }
  342.  
  343.                             Depth = 8;    /* For the sake of the compiler initialize this. */
  344.  
  345.                             for(i = 1 ; i <= 8 ; i++)
  346.                             {
  347.                                 if(MaxPen < (1 << i))
  348.                                 {
  349.                                     Depth = i;
  350.                                     break;
  351.                                 }
  352.                             }
  353.  
  354.                             Info->TabWidth    = MaxWidth;
  355.                             Info->TabHeight    = 4 + RPort->TxHeight + 5;
  356.  
  357.                             InitBitMap(&Mask,1,Info->TabWidth,Info->TabHeight);
  358.  
  359.                             Mask.Planes[1] = NULL;
  360.  
  361.                             for(i = 0 ; GotIt && i < 2 ; i++)
  362.                             {
  363.                                 if(!(Mask.Planes[i] = (PLANEPTR)AllocRaster(Info->TabWidth,Info->TabHeight)))
  364.                                     GotIt = FALSE;
  365.                             }
  366.  
  367.                             for(i = 0 ; GotIt && i < Info->Count ; i++)
  368.                             {
  369.                                 if(!(Info->Tabs[i].BitMap = LTP_CreateBitMap(Info->TabWidth,Info->TabHeight,Depth,NULL,TRUE)))
  370.                                     GotIt = FALSE;
  371.                             }
  372.  
  373.                             if(GotIt)
  374.                             {
  375.                                 Depth = LTP_GetDepth(Screen->RastPort.BitMap);
  376.  
  377.                                 if(!(Info->BitMap = LTP_CreateBitMap(gadget->Width,Info->TabHeight,Depth,Screen->RastPort.BitMap,FALSE)))
  378.                                     GotIt = FALSE;
  379.                             }
  380.  
  381.                             if(GotIt)
  382.                             {
  383.                                 struct TmpRas     TmpRas;
  384.                                 LONG             j,Len,Offset,Pos;
  385.  
  386.                                 InitTmpRas(&TmpRas,Mask.Planes[1],RASSIZE(Info->TabWidth,Info->TabHeight));
  387.  
  388.                                 RPort->TmpRas    = &TmpRas;
  389.                                 RPort->BitMap    = &Mask;
  390.  
  391.                                 SetRast(RPort,0);
  392.  
  393.                                 LTP_SetPens(RPort,1,0,JAM1);
  394.  
  395.                                 DrawCap(RPort,0,0,Lean,Info->TabHeight,TRUE);
  396.                                 LTP_DrawLine(RPort,Lean,0,Info->TabWidth - (Lean + 1),0);
  397.  
  398.                                 DrawCap(RPort,Info->TabWidth - Lean,0,Lean,Info->TabHeight,FALSE);
  399.                                 LTP_DrawLine(RPort,0,Info->TabHeight - 1,Info->TabWidth - 1,Info->TabHeight - 1);
  400.  
  401.                                 Flood(RPort,1,Info->TabWidth / 2,Info->TabHeight / 2);
  402.  
  403.                                 LTP_SetAPen(RPort,0);
  404.  
  405.                                 for(i = 0 ; i < 2 ; i++)
  406.                                 {
  407.                                     for(j = 0 ; j < Info->Thick ; j++)
  408.                                         WritePixel(RPort,j,Info->TabHeight - 1 - i);
  409.  
  410.                                     for(j = 0 ; j < Info->Thick ; j++)
  411.                                         WritePixel(RPort,Info->TabWidth - 1 - j,Info->TabHeight - 1 - i);
  412.                                 }
  413.  
  414.                                 WaitBlit();
  415.  
  416.                                 FreeRaster(Mask.Planes[1],Info->TabWidth,Info->TabHeight);
  417.  
  418.                                     // *VERY* important; leaving a dead TmpRas around will
  419.                                     // cause problems with Text() later as Gfx may use
  420.                                     // RPort->TmpRas for buffering.
  421.  
  422.                                 RPort->TmpRas = NULL;
  423.  
  424.                                 Offset = (Width - Info->Thick * 5) / Info->Count;
  425.  
  426.                                 while(Offset > 0 && Offset * (Info->Count - 1) + Info->TabWidth >= Width - Info->Thick * 5)
  427.                                     Offset--;
  428.  
  429.                                 if(Offset > Info->TabWidth + Info->Thick)
  430.                                     Offset = Info->TabWidth + Info->Thick;
  431.  
  432.                                 Pos = 2 * Info->Thick;
  433.  
  434.                                 for(i = 0 ; i < Info->Count ; i++)
  435.                                 {
  436.                                     RPort->BitMap = Info->Tabs[i].BitMap;
  437.  
  438.                                     Info->Tabs[i].Left = Pos;
  439.                                     Pos += Offset;
  440.  
  441.                                     SetRast(RPort,Pens[BACKGROUNDPEN]);
  442.  
  443.                                     LTP_SetAPen(RPort,Pens[SHINEPEN]);
  444.  
  445.                                     for(j = 0 ; j < Info->Thick ; j++)
  446.                                         DrawCap(RPort,Info->Thick + j,0,Lean,Info->TabHeight,TRUE);
  447.  
  448.                                     LTP_DrawLine(RPort,Info->Thick + Lean,0,Info->TabWidth - (Lean + 1) - Info->Thick,0);
  449.  
  450.                                     LTP_SetAPen(RPort,Pens[SHADOWPEN]);
  451.  
  452.                                     for(j = 0 ; j < Info->Thick ; j++)
  453.                                         DrawCap(RPort,Info->TabWidth - Lean - j - Info->Thick,0,Lean,Info->TabHeight,FALSE);
  454.  
  455.                                     LTP_SetAPen(RPort,Pens[TEXTPEN]);
  456.                                     Len = strlen(Labels[i]);
  457.  
  458.                                     LTP_PrintText(RPort,Labels[i],Len,(Info->TabWidth - TextLength(RPort,Labels[i],Len)) / 2,2);
  459.                                 }
  460.  
  461.                                 Info->Mask = Mask.Planes[0];
  462.  
  463.                                 Info->Offset = Offset;
  464.  
  465.                                 Info->RPort.BitMap = Info->BitMap;
  466.  
  467.                                 CloseFont(Font);
  468.  
  469.                                 return((ULONG)gadget);
  470.                             }
  471.                         }
  472.                     }
  473.                 }
  474.  
  475.                 CloseFont(Font);
  476.             }
  477.         }
  478.  
  479.         CoerceMethod(class,(Object *)gadget,OM_DISPOSE);
  480.     }
  481.  
  482.     return(0);
  483. }
  484.  
  485. STATIC ULONG
  486. InputMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  487. {
  488.     TabInfo    *Info    = INST_DATA(class,gadget);
  489.     ULONG     Result    = GMR_MEACTIVE;
  490.     LONG     x,y;
  491.     BOOL     Done    = FALSE;
  492.  
  493.     x = InputInfo->gpi_Mouse.X;
  494.     y = InputInfo->gpi_Mouse.Y;
  495.  
  496.     if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
  497.     {
  498.         if(InputInfo->gpi_IEvent->ie_Code == MENUDOWN)
  499.         {
  500.             Result    = GMR_NOREUSE;
  501.             Done    = TRUE;
  502.         }
  503.         else
  504.         {
  505.             if(InputInfo->gpi_IEvent->ie_Code == SELECTUP)
  506.             {
  507.                 Done = TRUE;
  508.  
  509.                 if(x >= 0 && x < gadget->Width && y >= 0 && y < gadget->Height)
  510.                 {
  511.                     Result = GMR_NOREUSE | GMR_VERIFY;
  512.  
  513.                     *InputInfo->gpi_Termination = Info->Current;
  514.                 }
  515.                 else
  516.                     Result = GMR_NOREUSE;
  517.             }
  518.         }
  519.     }
  520.  
  521.     if(Result == GMR_NOREUSE)
  522.     {
  523.         struct RastPort    *RPort;
  524.  
  525.         if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  526.         {
  527.             Info->Current = Info->Initial;
  528.  
  529.             DoMethod((Object *)gadget,GM_RENDER,InputInfo->gpi_GInfo,RPort,GREDRAW_REDRAW);
  530.  
  531.             ReleaseGIRPort(RPort);
  532.         }
  533.     }
  534.  
  535.     if(!Done)
  536.     {
  537.         if(x >= 0 && x < gadget->Width && y >= 0 && y < gadget->Height)
  538.         {
  539.             LONG Index,i;
  540.  
  541.             for(Index = -1, i = Info->Count - 1 ; i >= 0 ; i--)
  542.             {
  543.                 if(x >= Info->Tabs[i].Left && x < Info->Tabs[i].Left + Info->TabWidth)
  544.                     Index = i;
  545.             }
  546.  
  547.             if(Index != Info->Current && Index != -1)
  548.             {
  549.                 struct RastPort    *RPort;
  550.  
  551.                 if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  552.                 {
  553.                     Info->Current = Index;
  554.  
  555.                     DoMethod((Object *)gadget,GM_RENDER,InputInfo->gpi_GInfo,RPort,GREDRAW_UPDATE);
  556.  
  557.                     ReleaseGIRPort(RPort);
  558.                 }
  559.             }
  560.         }
  561.     }
  562.  
  563.     return(Result);
  564. }
  565.  
  566. STATIC ULONG
  567. ActiveMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  568. {
  569.     TabInfo            *Info = INST_DATA(class,gadget);
  570.     struct RastPort    *RPort;
  571.  
  572.     if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  573.     {
  574.         LONG Current,i;
  575.         LONG x;
  576.  
  577.         x = InputInfo->gpi_Mouse.X;
  578.  
  579.         for(Current = -1, i = Info->Count - 1 ; i >= 0 ; i--)
  580.         {
  581.             if(x >= Info->Tabs[i].Left && x < Info->Tabs[i].Left + Info->TabWidth)
  582.                 Current = i;
  583.         }
  584.  
  585.         Info->Initial = Info->Current;
  586.  
  587.         if(Current != Info->Current && Current != -1)
  588.         {
  589.             Info->Current = Current;
  590.  
  591.             DoMethod((Object *)gadget,GM_RENDER,InputInfo->gpi_GInfo,RPort,GREDRAW_UPDATE);
  592.         }
  593.  
  594.         ReleaseGIRPort(RPort);
  595.  
  596.         return(GMR_MEACTIVE);
  597.     }
  598.     else
  599.         return(GMR_NOREUSE);
  600. }
  601.  
  602. STATIC ULONG
  603. InactiveMethod(struct IClass *class,struct Gadget *gadget,struct gpGoInactive *InactiveInfo)
  604. {
  605.     TabInfo            *Info = INST_DATA(class,gadget);
  606.     struct RastPort    *RPort;
  607.     LONG             Index;
  608.  
  609.     if(InactiveInfo->gpgi_Abort)
  610.         Index = Info->Initial;
  611.     else
  612.         Index = Info->Current;
  613.  
  614.     if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  615.     {
  616.         Info->Current = Index;
  617.  
  618.         DoMethod((Object *)gadget,GM_RENDER,InactiveInfo->gpgi_GInfo,RPort,GREDRAW_REDRAW);
  619.  
  620.         ReleaseGIRPort(RPort);
  621.     }
  622.  
  623.     return(0);
  624. }
  625.  
  626. BOOL
  627. LTP_ObtainTabSize(struct IBox *Box,...)
  628. {
  629.     va_list             VarArgs;
  630.     struct TagItem    *TagList,*Tag;
  631.     struct TextAttr    *FontAttr;
  632.     struct DrawInfo    *DrawInfo;
  633.     STRPTR            *Labels;
  634.     LONG             Count;
  635.     LONG             SizeType;
  636.     BOOL             Success;
  637.  
  638.     Success = FALSE;
  639.  
  640.     va_start(VarArgs,Box);
  641.  
  642.     TagList = (struct TagItem *)VarArgs;
  643.  
  644.     SizeType = GDOMAIN_NOMINAL;
  645.     FontAttr = NULL;
  646.     DrawInfo = NULL;
  647.     Labels = NULL;
  648.  
  649.     while(Tag = NextTagItem(&TagList))
  650.     {
  651.         switch(Tag->ti_Tag)
  652.         {
  653.             case TIA_Labels:
  654.                 Labels = (STRPTR *)Tag->ti_Data;
  655.                 break;
  656.  
  657.             case TIA_Font:
  658.                 FontAttr = (struct TextAttr *)Tag->ti_Data;
  659.                 break;
  660.  
  661.             case TIA_DrawInfo:
  662.                 DrawInfo = (struct DrawInfo *)Tag->ti_Data;
  663.                 break;
  664.  
  665.             case TIA_SizeType:
  666.                 SizeType = Tag->ti_Data;
  667.                 break;
  668.         }
  669.     }
  670.  
  671.     Count = 0;
  672.  
  673.     if(Labels)
  674.     {
  675.         while(Labels[Count])
  676.             Count++;
  677.     }
  678.  
  679.     if(DrawInfo && FontAttr && Labels && Count)
  680.     {
  681.         struct TextFont *Font;
  682.  
  683.         if(Font = OpenFont(FontAttr))
  684.         {
  685.             struct RastPort    RastPort,*RPort = &RastPort;
  686.             LONG            i,Len,MaxWidth;
  687.             LONG            Lean,Thick;
  688.  
  689.             InitRastPort(RPort);
  690.  
  691.             SetFont(RPort,Font);
  692.  
  693.             Box->Left    = 0;
  694.             Box->Top    = 0;
  695.             Box->Height    = RPort->TxHeight + 11;
  696.  
  697.             Lean = (TextLength(RPort,"O",1) + 1) / 2;
  698.  
  699.             Thick = (DrawInfo->dri_Resolution.Y + DrawInfo->dri_Resolution.X - 1) / DrawInfo->dri_Resolution.X;
  700.  
  701.             if(Thick < 1)
  702.                 Thick = 1;
  703.  
  704.             for(i = MaxWidth = 0 ; i < Count ; i++)
  705.             {
  706.                 if((Len = TextLength(RPort,Labels[i],strlen(Labels[i]))) > MaxWidth)
  707.                     MaxWidth = Len;
  708.             }
  709.  
  710.             MaxWidth = 2 + (Lean + Thick - 1 + Thick + MaxWidth + Thick + Lean + Thick - 1) + 2;
  711.  
  712.             if(SizeType == GDOMAIN_MINIMUM && Count > 1)
  713.                 Box->Width = 2 * Thick + MaxWidth + (Count - 1) * (Thick * 4) + Thick * 3;
  714.             else
  715.                 Box->Width = 2 * Thick + Count * (MaxWidth + Thick) + Thick * 2;
  716.  
  717.             CloseFont(Font);
  718.  
  719.             Success = TRUE;
  720.         }
  721.     }
  722.  
  723.     va_end(VarArgs);
  724.  
  725.     return(Success);
  726. }
  727.  
  728. ULONG SAVE_DS ASM
  729. LTP_TabClassDispatcher(REG(a0) struct IClass *class,REG(a2) Object *object,REG(a1) Msg msg)
  730. {
  731.     switch(msg->MethodID)
  732.     {
  733.         case OM_NEW:
  734.             return(NewMethod(class,(struct Gadget *)object,(struct opSet *)msg));
  735.  
  736.         case OM_UPDATE:
  737.         case OM_SET:
  738.             SetMethod(class,(struct Gadget *)object,(struct opSet *)msg);
  739.             break;
  740.  
  741.         case GM_RENDER:
  742.             return(RenderMethod(class,(struct Gadget *)object,(struct gpRender *)msg));
  743.  
  744.         case GM_HITTEST:
  745.             return(GMR_GADGETHIT);
  746.  
  747.         case GM_GOINACTIVE:
  748.             return(InactiveMethod(class,(struct Gadget *)object,(struct gpGoInactive *)msg));
  749.  
  750.         case GM_HANDLEINPUT:
  751.             return(InputMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  752.  
  753.         case GM_GOACTIVE:
  754.             return(ActiveMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  755.  
  756.         case OM_DISPOSE:
  757.             DisposeMethod(class,(struct Gadget *)object,msg);
  758.  
  759.             // Falls down through to the default case...
  760.     }
  761.  
  762.     return(DoSuperMethodA(class,object,msg));
  763. }
  764.  
  765. #endif    /* DO_TAB_KIND */
  766.